<template>
  <div ref="three-canvas" class="fixed w-screen h-screen"></div>
</template>

<script setup lang="ts">
import * as THREE from 'three'

const threeCanvas = useTemplateRef('three-canvas')

// 初始化 Three.js
let renderer: THREE.WebGLRenderer | null,
  scene: THREE.Scene | null,
  camera: THREE.PerspectiveCamera | null,
  animationId: number | undefined
const initThree = (parent: HTMLElement) => {
  // 创建场景
  scene = new THREE.Scene()
  // 创建相机
  camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 500)
  camera.position.set(0, 0, 100)
  camera.lookAt(0, 0, 0)
  // 创建渲染器
  renderer = new THREE.WebGLRenderer()
  renderer.setSize(window.innerWidth, window.innerHeight)
  parent.appendChild(renderer.domElement)
  // 创建一个定向灯
  const light = new THREE.DirectionalLight(0xffffff, 3)
  light.position.set(-1, 2, 4)
  scene.add(light)
  // 创建线条
  const points = []
  points.push(new THREE.Vector3(-10, 0, 0))
  points.push(new THREE.Vector3(0, 10, 0))
  points.push(new THREE.Vector3(10, 0, 0))
  const geometry = new THREE.BufferGeometry().setFromPoints(points)
  const material = new THREE.LineBasicMaterial({ color: 0x00ff00 })
  const line = new THREE.Line(geometry, material)
  scene.add(line)
  renderer.render(scene, camera)
}

// 销毁 Three.js
const disposeThree = () => {
  animationId && cancelAnimationFrame(animationId)

  // 销毁几何体和材质
  if (scene) {
    scene.traverse((object) => {
      // 确保仅处理 Mesh 类型的对象
      if (object instanceof THREE.Mesh) {
        if (object.geometry) {
          object.geometry.dispose()
        }
        // 处理可能是数组的材质
        if (Array.isArray(object.material)) {
          object.material.forEach((material) => material.dispose())
        } else {
          object.material.dispose()
        }
      }
    })
  }

  // 销毁渲染器
  if (renderer) {
    renderer.dispose()
    renderer.forceContextLoss()
    //   renderer.domElement = null
  }

  scene = null
  camera = null
  renderer = null
}

// 响应窗口大小变化
const onResize = () => {
  if (camera && renderer) {
    camera.aspect = window.innerWidth / window.innerHeight
    camera.updateProjectionMatrix()
    renderer.setSize(window.innerWidth, window.innerHeight)
  }
}

// 生命周期钩子
onMounted(() => {
  initThree(threeCanvas.value!)
  window.addEventListener('resize', onResize)
})

onUnmounted(() => {
  disposeThree()
  window.removeEventListener('resize', onResize)
})
</script>

<style scoped lang="scss"></style>
